//--------------------------------------------------------------------------
// 
//  Copyright (c) Chili Software.  All rights reserved. 
// 
//  File: ObjectViewManager_1.cs
//
//  Description: Manage ObjectViews of an ObjectSet.
// 
//--------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.ComponentModel;

namespace Chili.Opf3
{
	/// <summary>
	/// This class manages the <see cref="ObjectView{T}">ObjectViews</see> of an <see cref="ObjectSet{T}">ObjectSet</see>.
	/// </summary>
	internal sealed class ObjectViewManager<T>
	{
		private List<WeakReference> _views = new List<WeakReference>();
		private ObjectSet<T> _objectSet;

		/// <summary>
		/// Creates a new instance of the <see cref="ObjectViewManager{T}">ObjectViewManager Class</see>.
		/// </summary>
		/// <param name="objectSet">The <see cref="ObjectSet{T}">ObjectSet</see> associated with the manager.</param>
		public ObjectViewManager(ObjectSet<T> objectSet)
		{
			if (objectSet == null)
				throw new ArgumentNullException("objectSet");

			_objectSet = objectSet;
		}

		/// <summary>
		/// Notifies the <see cref="ObjectView{T}">ObjectViews</see> that the list of the <see cref="ObjectSet{T}">ObjectSet</see>
		/// has changed.
		/// </summary>
		/// <param name="e">The EventArgs argument passed with the event that fired the change of the list.</param>
		public void NotifyListChanged(ListChangedEventArgs e)
		{
			lock (this)
			{
				// Clean all views where the reference is no longer valid.
				List<int> deadIndexes = new List<int>();

				for(int i = 0; i < _views.Count; i++)
				{
					WeakReference wr = _views[i];

					ObjectView<T> view = (ObjectView<T>)wr.Target;
					if (view == null)
						deadIndexes.Add(i);

					// Notify the view that the list has been changed.
					view.NotifyListChanged(_objectSet, e);
				}

				// Clear the dead references.
				foreach(int index in deadIndexes)
				{
					_views.RemoveAt(index);
				}
			}
		}

		/// <summary>
		/// Registers an <see cref="ObjectView{T}">ObjectView</see> in the manager.
		/// </summary>
		/// <param name="view">The <see cref="ObjectView{T}">ObjectView</see> that is registered.</param>
		public void RegisterView(ObjectView<T> view)
		{
			lock (this)
			{
				_views.Add(new WeakReference(view));
			}
		}

		/// <summary>
		/// Unregisters an <see cref="ObjectView{T}">ObjectView</see> in the manager.
		/// </summary>
		/// <param name="view">The <see cref="ObjectView{T}">ObjectView</see> that is unregistered.</param>
		public void UnRegisterView(ObjectView<T> view)
		{
			lock (this)
			{
				for (int i = 0; i < _views.Count; i++)
				{
					WeakReference wr = _views[i];

					if (wr.Target == view)
					{
						_views.RemoveAt(i);
						return;
					}
				}
			}
		}
	}
}
